<template>
  <div class="card fileUpload">
    <splitpanes :dbl-click-splitter="false" style="display: flex; height: 100%; background-color: #ffffff">
      <pane size="15">
        <div class="leftTree">
          <el-tree-select
            style="width: 100%; margin: 8px 0 5px"
            check-strictly
            v-model="Fonds_ID"
            placeholder="请选择全宗"
            @change="onChange"
            node-key="Fonds_ID"
            :props="{ label: 'Fonds_Name', children: 'children' }"
            :data="FondsData"
            :render-after-expand="false"
          />
          <el-select
            style="width: 100%"
            check-strictly
            v-model="FM_ID"
            placeholder="请选择门类"
            @change="onChangeFM"
            :render-after-expand="false"
          >
            <el-option v-for="item in FMData" :key="item.FM_ID" :label="item.FM_OCName" :value="item.FM_ID" />
          </el-select>
          <!-- 搜索栏 -->
          <el-input v-model="searchVal" placeholder="请输入想要搜索的内容" enter-button @change="onSearch" />
          <ztree
            :setting="treeSetting.setting"
            :nodes="treeSetting.treeData"
            @onClick="onClick"
            @onCreated="handleCreated"
          ></ztree>
        </div>
      </pane>
      <pane size="85">
        <div class="upload-box">
          <!-- 文件上传区域 -->
          <div class="upload-section">
            <h3>文件上传</h3>
            <el-upload
              ref="uploadZip"
              class="upload-demo"
              :auto-upload="false"
              drag
              accept=".zip"
              :limit="1"
              :on-change="onChangeFile"
            >
              <el-icon class="el-icon--upload"><upload-filled /></el-icon>
              <div class="el-upload__text">请拖拽或 <em>点击此处上传</em></div>
              <template #tip>
                <div class="el-upload__tip">请上传zip格式</div>
              </template>
            </el-upload>
            <div v-if="fileList.length > 0" class="file-info">
              <div class="file-name">{{ fileList[0]?.name }}</div>
              <div class="file-size">{{ formatFileSize(fileList[0]?.size || 0) }}</div>
            </div>
            <el-progress v-if="progressShow" :text-inside="true" :stroke-width="26" :percentage="totalProgress" />
            <span v-if="speedShow" style="display: block; margin: 10px 0">
              上传速度: {{ speedMBps }} MB/s 预计剩余时间: {{ remainingTimeStr }}
            </span>
            <span v-if="uploadFailed && progressShow" style="display: block; margin: 10px 0; font-weight: bold; color: #f56c6c">
              上传失败
            </span>
            <span
              v-if="totalProgress === 100 && progressShow"
              style="display: block; margin: 10px 0; font-weight: bold; color: #67c23a"
            >
              上传成功
            </span>
            <div class="btn">
              <el-button type="success" @click="uploadEvent">上传</el-button>
              <el-button v-show="btnShow" type="danger" @click="togglePause">{{ isPaused ? "继续" : "暂停" }}</el-button>
            </div>
          </div>

          <!-- 文件导入区域 -->
          <div class="import-section">
            <h3>文件导入</h3>
            <div class="path-input-container">
              <el-input
                v-model="fileUrl"
                placeholder="请输入zip文件的完整路径"
                :disabled="true"
                @keyup.enter="importFile"
                :class="{ 'is-valid': isPathValid && fileUrl.trim(), 'is-invalid': fileUrl.trim() && !isPathValid }"
              />
            </div>
            <div class="import-tip">
              提示：路径格式示例：G://appaa//TestUploadFile2DBAPI//TestUploadFile2DBAPI//wwwroot//folder//file.zip
            </div>
            <div v-if="fileUrl.trim()" class="validation-message" :class="{ valid: isPathValid, invalid: !isPathValid }">
              {{ isPathValid ? "✓ 路径格式正确" : "✗ 请输入有效的ZIP文件路径" }}
            </div>
            <div v-if="importStatus === 'success'" style="margin: 5px 0 0; font-weight: bold; color: #67c23a">导入成功</div>
            <div v-if="importStatus === 'fail'" style="margin: 5px 0 0; font-weight: bold; color: #f56c6c">导入失败</div>
            <el-button ref="importFileRef" type="primary" @click="importFile" :loading="importing" :disabled="!canImport">
              {{ importing ? "导入中..." : "导入文件" }}
            </el-button>
          </div>
        </div>
      </pane>
    </splitpanes>
    <el-dialog v-model="uploadVisible" width="300" :show-close="false" :close-on-click-modal="false">
      <div class="progress-item">
        <div class="progress-label">
          <span>文件 MD5 计算</span>
          <span class="md5-percentage">{{ MD5Count }}%</span>
        </div>
        <el-progress :percentage="MD5Progress" />
      </div>
      <div class="progress-item">
        <div class="progress-label">
          <span>分片 Hash 计算</span>
          <span class="chunk-percentage">{{ HashCount }}%</span>
        </div>
        <el-progress :percentage="HashProgress" />
      </div>
      <div class="status-text">{{ uploadTxt }}</div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import SparkMD5 from "spark-md5";
import Ztree from "@/components/ztree/Ztree.vue";
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
import { ref, reactive, onMounted, computed } from "vue";
import { getCatalog } from "@/views/system/catalogManage/events";
import { transTree } from "@/utils/util";
import useCurrentInstance from "@/utils/useCurrentInstance";

// 定义类型
interface FileChunkInfo {
  file: File;
  fileName: string;
  fileMd5: string;
  chunkHash: string;
  start: number;
  end: number;
  partNumber: number;
  chunks: number;
  size: number;
  total: number;
  urlParameter: string;
}

interface UploadStatus {
  fileName: string;
  fileMd5: string;
  totalSize: number;
  totalChunks: number;
  uploadedChunks: Set<number>;
  startTime?: string;
}

interface ChunkInfo {
  hash: string;
  isCompleted: boolean;
  chunkNumber: number;
}

interface CheckFileResult {
  exists: boolean;
  filePath?: string;
}

const { proxy } = useCurrentInstance();

// 上传文件详情弹框底部显示文字
const uploadTxt = ref("正在处理...");
// 导入文件按钮实例
const importFileRef = ref<any>(null);
// 上传文件组件实例
const uploadZip = ref<any>(null);
// 上传文件列表
const fileList = ref<any[]>([]);
// 上传文件详情弹框
const uploadVisible = ref(false);
// 文件地址
const fileUrl = ref("");
// 暂停按钮是否显示
const btnShow = ref(false);
// 进度条是否显示
const progressShow = ref(false);
// 是否暂停
const isPaused = ref(false);
// 上传队列
const uploadQueue = ref<FileChunkInfo[]>([]);
// 总上传进度
const totalProgress = ref(0);
// 总文件大小
const totalSize = ref(0);
// 总分片数
const totalChunks = ref(0);
// 已经上传的分片
const completedChunks = ref(0);
// 已经上传的文件大小
const uploadedSize = ref(0);
// 上传速度是否显示
const speedShow = ref(false);
const uploadFailed = ref(false); // 上传失败状态
// 是否正在导入文件
const importing = ref(false);
const importStatus = ref(""); // "success" | "fail" | ""
// 导入历史记录
const importHistory = ref<string[]>([]);
// 统计信息
const stats = reactive({
  totalUploads: 0,
  totalImports: 0,
  lastUploadTime: "",
  lastImportTime: ""
});
// 上传速度
const speedMBps = ref("0");
// 剩余时间
const remainingTimeStr = ref("--:--");
// 上传文件详情弹框进度条进度
const MD5Progress = ref(0);
const HashProgress = ref(0);
// 上传文件详情弹框百分比
const MD5Count = ref(0);
const HashCount = ref(0);
// 上传文件开始时间
const startTime = ref<Date | null>(null);
// 当前上传的状态
const currentUploadStatus = reactive<UploadStatus>({
  fileName: "",
  fileMd5: "",
  totalSize: 0,
  totalChunks: 0,
  uploadedChunks: new Set()
});

// 计算属性：文件路径是否有效
const isPathValid = computed(() => {
  return fileUrl.value.trim() && validatePath(fileUrl.value);
});

// 计算属性：是否可以导入
const canImport = computed(() => {
  return isPathValid.value && !importing.value;
});

// 全宗数据
const FondsData = ref<any[]>([]);
// 全宗绑定字段
const Fonds_ID = ref("");
// 门类数据
const FMData = ref<any[]>([]);
// 门类绑定字段
const FM_ID = ref("");
// 搜索条件
const searchVal = ref("");
// 全宗tree配置
const treeSetting = reactive({
  setting: {
    // ztree配置
    data: {
      simpleData: {
        enable: true,
        idKey: "Catalog_ID",
        pIdKey: "Catalog_Father"
      },
      key: {
        name: "Catalog_Name"
      }
    },
    view: {
      showIcon: false
    }
  },
  treeData: [] as any[],
  treeNode: {} as any
});
// 初始化树对象
const ztreeObj = ref();

// 改变文件函数
const onChangeFile = (file: any, filelist: any) => {
  fileList.value = filelist;
};

// 点击上传文件
const uploadEvent = () => {
  if (fileList.value.length === 0) {
    proxy.$message.error("请选择文件");
    return;
  }
  resetUpload();
  uploadFailed.value = false; // 重置失败状态
  UploadFile();
};

// 初始化上传
const resetUpload = () => {
  isPaused.value = false;
  uploadQueue.value = [];
  totalProgress.value = 0;
  completedChunks.value = 0;
  uploadedSize.value = 0;
  btnShow.value = true;
  progressShow.value = true;
  uploadVisible.value = true;
  speedShow.value = true;
  startTime.value = new Date();
  uploadFailed.value = false; // 重置失败状态
};

// 暂停/继续
const togglePause = () => {
  isPaused.value = !isPaused.value;
  if (!isPaused.value) {
    processQueue();
  }
};

// UploadFile函数
const UploadFile = async () => {
  const file = fileList.value[0]?.raw || fileList.value[0];
  if (!file) {
    proxy.$message.error("请选择文件");
    return;
  }

  // 获取原始文件名
  const fileName = file.name;
  console.log("开始上传文件:", {
    fileName: fileName,
    fileSize: file.size,
    startTime: new Date().toISOString()
  });

  // 重置并显示进度指示器
  MD5Count.value = 0;
  HashCount.value = 0;
  MD5Progress.value = 0;
  HashProgress.value = 0;
  uploadTxt.value = "正在计算文件 MD5...";

  try {
    // 计算整个文件的 MD5
    const fileMd5 = await calculateFileMD5(file);
    console.log("文件 MD5 计算完成:", fileMd5);

    // 检查文件是否可以秒传
    const checkResult = await checkFileExists(fileMd5, fileName);
    if (checkResult.exists) {
      totalProgress.value = 100;
      uploadVisible.value = false;
      fileUrl.value = checkResult.filePath || "";
      // if (importFileRef.value) {
      //   importFileRef.value.click();
      // }
      setTimeout(() => {
        // progressShow.value = false;
        proxy.$message.success("文件秒传成功！");
      }, 1000);
      return;
    }

    // 准备分片上传
    totalSize.value = file.size;
    const bufferChunkSize = getOptimalChunkSize(file.size);
    const totalChunksCount = Math.ceil(totalSize.value / bufferChunkSize);

    // 初始化上传状态
    currentUploadStatus.fileName = fileName;
    currentUploadStatus.fileMd5 = fileMd5;
    currentUploadStatus.totalSize = totalSize.value;
    currentUploadStatus.totalChunks = totalChunksCount;
    currentUploadStatus.uploadedChunks = new Set();
    currentUploadStatus.startTime = new Date().toISOString();

    // 获取已上传的分片信息
    const uploadStatus = await checkUploadStatus(fileName, fileMd5, totalSize.value, totalChunksCount);

    // 重置计数器
    completedChunks.value = 0;
    uploadedSize.value = 0;
    uploadQueue.value = [];

    // 处理每个分片
    for (let partNumber = 1; partNumber <= totalChunksCount; partNumber++) {
      const start = (partNumber - 1) * bufferChunkSize;
      const end = partNumber === totalChunksCount ? file.size : Math.min(start + bufferChunkSize, file.size);

      const chunk = file.slice(start, end);
      const chunkSize = end - start;

      // 更新分片计算进度显示
      let chunkProgress = Math.round((partNumber / totalChunksCount) * 100);
      HashCount.value = chunkProgress;
      HashProgress.value = chunkProgress;
      uploadTxt.value = `正在计算分片 Hash (${partNumber}/${totalChunksCount})`;

      // 计算分片的 hash
      const chunkHash = await calculateChunkHash(chunk);
      console.log(`分片 ${partNumber} hash 计算完成:`, {
        partNumber,
        hash: chunkHash,
        size: chunkSize
      });

      // 检查分片是否已上传
      if (uploadStatus?.chunks?.some((c: ChunkInfo) => c.hash === chunkHash && c.isCompleted)) {
        console.log(`分片 ${partNumber} 已存在，跳过上传`);
        completedChunks.value++;
        uploadedSize.value += chunkSize;
        currentUploadStatus.uploadedChunks.add(partNumber);
        continue;
      }

      // 准备分片信息
      let fileChunkInfo: FileChunkInfo = {
        file: chunk,
        fileName: fileName,
        fileMd5: fileMd5,
        chunkHash: chunkHash,
        start: start,
        end: end,
        partNumber: partNumber,
        chunks: totalChunksCount,
        size: chunkSize,
        total: file.size,
        urlParameter: ""
      };

      // 构建URL参数
      const url =
        `partNumber=${partNumber}` +
        `&chunks=${totalChunksCount}` +
        `&size=${chunkSize}` +
        `&start=${start}` +
        `&end=${end}` +
        `&total=${file.size}` +
        `&fileName=${encodeURIComponent(fileName)}` +
        `&fileMd5=${fileMd5}` +
        `&chunkHash=${chunkHash}`;

      fileChunkInfo.urlParameter = url;
      uploadQueue.value.push(fileChunkInfo);

      // 输出分片准备信息
      console.log(`分片 ${partNumber} 准备完成:`, {
        start,
        end,
        size: chunkSize,
        hash: chunkHash,
        isLastChunk: partNumber === totalChunksCount
      });
    }

    // 隐藏hash计算的加载指示器
    uploadVisible.value = false;

    // 更新总进度显示
    const progress = (uploadedSize.value / totalSize.value) * 100;
    totalProgress.value = progress;

    console.log("待上传分片数量:", uploadQueue.value.length);

    // 如果所有分片都已上传，直接完成
    if (uploadQueue.value.length === 0) {
      totalProgress.value = 100;
      uploadFailed.value = false;
      proxy.$message.success("文件上传成功！");
      return;
    }

    // 开始上传剩余的分片
    startTime.value = new Date();
    totalChunks.value = totalChunksCount;
    processQueue();

    console.log("开始上传分片:", {
      totalChunks: totalChunksCount,
      remainingChunks: uploadQueue.value.length,
      startTime: startTime.value.toISOString()
    });
  } catch (error: any) {
    // 错误处理
    console.error("文件处理失败:", {
      error: error.message,
      fileName: fileName,
      timeStamp: new Date().toISOString()
    });
    uploadVisible.value = false;
    proxy.$message.error("文件处理失败，请重试");
    progressShow.value = false;
    btnShow.value = false;
    uploadFailed.value = true; // 上传失败
  }
};

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return "0 Bytes";
  const k = 1024;
  const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
};

// 验证文件路径
const validatePath = (path: string): boolean => {
  return path.trim().toLowerCase().endsWith(".zip");
};

// 删除历史记录
const removeHistory = (index: number) => {
  importHistory.value.splice(index, 1);
  saveHistoryToStorage();
};

// 保存历史记录到本地存储
const saveHistoryToStorage = () => {
  try {
    localStorage.setItem("importHistory", JSON.stringify(importHistory.value));
  } catch (error) {
    console.error("保存历史记录失败:", error);
  }
};

// 从本地存储加载历史记录
const loadHistoryFromStorage = () => {
  try {
    const saved = localStorage.getItem("importHistory");
    if (saved) {
      importHistory.value = JSON.parse(saved);
    }
  } catch (error) {
    console.error("加载历史记录失败:", error);
  }
};

// 保存统计信息到本地存储
const saveStatsToStorage = () => {
  try {
    localStorage.setItem("uploadStats", JSON.stringify(stats));
  } catch (error) {
    console.error("保存统计信息失败:", error);
  }
};

// 从本地存储加载统计信息
const loadStatsFromStorage = () => {
  try {
    const saved = localStorage.getItem("uploadStats");
    if (saved) {
      const savedStats = JSON.parse(saved);
      Object.assign(stats, savedStats);
    }
  } catch (error) {
    console.error("加载统计信息失败:", error);
  }
};

// 导入文件
const importFile = async () => {
  const zipPath = fileUrl.value.trim();

  if (!zipPath) {
    proxy.$message.error("请输入ZIP文件路径");
    importStatus.value = "";
    return;
  }

  if (!validatePath(zipPath)) {
    proxy.$message.error("请输入有效的ZIP文件路径");
    importStatus.value = "";
    return;
  }

  try {
    importing.value = true;
    importStatus.value = "";

    // 构建URL，添加ZipFilePath参数
    const importUrl = `Values/ImportFile/importfile?ZipFilePath=${encodeURIComponent(zipPath)}`;

    // 发送请求
    const response = await proxy.$vueAxios.post(
      importUrl,
      {
        filePath: zipPath,
        catalogId: treeSetting.treeNode.Catalog_ID
      },
      { noLoading: true }
    );

    if (response && response.Mark) {
      proxy.$message.success("文件导入成功！");
      importStatus.value = "success";
      // 更新统计信息
      stats.totalImports++;
      stats.lastImportTime = new Date().toLocaleString();
      saveStatsToStorage();
      // 保存到历史记录
      if (!importHistory.value.includes(zipPath)) {
        importHistory.value.unshift(zipPath);
        // 只保留最近10条记录
        if (importHistory.value.length > 10) {
          importHistory.value = importHistory.value.slice(0, 10);
        }
        saveHistoryToStorage();
      }
      // 清空输入
      fileUrl.value = "";
    } else {
      proxy.$message.error("文件导入失败，请重试");
      importStatus.value = "fail";
    }
  } catch (error: any) {
    console.error("导入失败:", error);
    proxy.$message.error(`操作失败: ${error.message || "未知错误"}`);
    importStatus.value = "fail";
  } finally {
    importing.value = false;
  }
};

// 辅助函数：获取文件的md5值
const calculateFileMD5 = (file: File): Promise<string> => {
  return new Promise((resolve, reject) => {
    let blobSlice = File.prototype.slice || (File.prototype as any).mozSlice || (File.prototype as any).webkitSlice;
    let chunkSize = 2097152; // 2MB
    let chunks = Math.ceil(file.size / chunkSize);
    let currentChunk = 0;
    let spark = new SparkMD5.ArrayBuffer();
    let fileReader = new FileReader();

    uploadTxt.value = "正在计算文件 MD5...";

    fileReader.onload = function (e) {
      if (e.target?.result) {
        spark.append(e.target.result as ArrayBuffer);
        currentChunk++;
        // 更新MD5计算进度
        let progress = Math.round((currentChunk / chunks) * 100);
        MD5Count.value = progress;
        MD5Progress.value = progress;
        if (currentChunk < chunks) {
          loadNext();
        } else {
          let md5 = spark.end();
          resolve(md5);
        }
      }
    };

    fileReader.onerror = e => {
      console.log(e);
      uploadVisible.value = false;
      reject(e);
    };

    function loadNext() {
      let start = currentChunk * chunkSize;
      let end = start + chunkSize >= file.size ? file.size : start + chunkSize;
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }

    loadNext();
  });
};

// 辅助函数：检查文件是否可以秒传
const checkFileExists = async (fileMd5: string, fileName: string): Promise<CheckFileResult> => {
  try {
    const data = {
      md5: fileMd5,
      fileName: fileName
    };
    const res = await proxy.$vueAxios.post("upload/CheckFileExists", data, { noLoading: true });
    return res;
  } catch (error) {
    console.error("检查文件失败:", error);
    return { exists: false };
  }
};

// 辅助函数：获取最优分片大小
const getOptimalChunkSize = (fileSize: number): number => {
  let chunkSize;
  if (fileSize <= 100 * 1024 * 1024) {
    // <= 100MB
    chunkSize = 10 * 1024 * 1024; // 10MB
  } else if (fileSize <= 1024 * 1024 * 1024) {
    // <= 1GB
    chunkSize = 20 * 1024 * 1024; // 20MB
  } else {
    chunkSize = 10 * 1024 * 1024; // 默认10MB
  }

  // 确保最后一个分片不会太小
  const totalChunks = Math.ceil(fileSize / chunkSize);
  const lastChunkSize = fileSize - (totalChunks - 1) * chunkSize;

  if (lastChunkSize < 1024 * 1024) {
    // 如果最后一个分片小于1MB
    chunkSize = Math.ceil(fileSize / (totalChunks - 1));
  }

  return chunkSize;
};

// 辅助函数：检查文件上传状态
const checkUploadStatus = async (fileName: string, fileMd5: string, totalSize: number, totalChunks: number) => {
  try {
    const data = {
      fileName: fileName,
      fileMd5: fileMd5,
      totalSize: totalSize,
      totalChunks: totalChunks
    };
    const response = await proxy.$vueAxios.post("upload/GetUploadStatus", data, { noLoading: true });

    if (response && response.chunks) {
      // 更新已上传的分片信息
      currentUploadStatus.uploadedChunks = new Set(
        response.chunks.filter((chunk: ChunkInfo) => chunk.isCompleted).map((chunk: ChunkInfo) => chunk.chunkNumber)
      );
    }

    return response;
  } catch (error) {
    console.error("检查上传状态失败:", error);
    return null;
  }
};

// 辅助函数：计算单个分片的hash
const calculateChunkHash = async (chunk: File): Promise<string> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = e => {
      if (e.target?.result) {
        const spark = new SparkMD5.ArrayBuffer();
        spark.append(e.target.result as ArrayBuffer);
        const hash = spark.end();
        resolve(hash);
      }
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(chunk);
  });
};

// 修改processQueue函数以支持断点续传
const processQueue = () => {
  if (isPaused.value || uploadQueue.value.length === 0) return;
  // 获取队列中的下一个分片
  const chunk = uploadQueue.value.shift();
  if (chunk) {
    UploadFileChunk(chunk);
  }
};

// 优化分片上传函数
const UploadFileChunk = (chunk: FileChunkInfo) => {
  let data = new FormData();
  data.append("file", chunk.file, chunk.fileName);

  const updatedUrl = "upload/upload?" + chunk.urlParameter + "&fileName=" + encodeURIComponent(chunk.fileName);

  proxy.$vueAxios
    .post(updatedUrl, data, { noLoading: true })
    .then((res: any) => {
      console.log("分片上传成功:", chunk.partNumber);
      currentUploadStatus.uploadedChunks.add(chunk.partNumber);
      updateProgress(chunk.file.size);
      if (!isPaused.value) {
        processQueue();
      }
      uploadFailed.value = false; // 上传成功时重置失败状态
    })
    .catch((error: any) => {
      console.error("分片上传失败:", chunk.partNumber, error);
      uploadQueue.value.unshift(chunk);
      setTimeout(function () {
        if (!isPaused.value) {
          processQueue();
        }
      }, 3000); // 3秒后重试
      uploadFailed.value = true; // 分片上传失败
    });
};

// 修改updateProgress函数以支持更精确的进度显示
const updateProgress = (chunkSize: number) => {
  completedChunks.value++;
  uploadedSize.value += chunkSize;
  const progress = (uploadedSize.value / totalSize.value) * 100;
  totalProgress.value = Math.round(progress);

  // 只在有实际上传时才更新速度和剩余时间
  if (uploadQueue.value.length > 0 && startTime.value) {
    const currentTime = new Date();
    const duration = (currentTime.getTime() - startTime.value.getTime()) / 1000;
    const speed = uploadedSize.value / duration;
    const speedMBps2 = (speed / (1024 * 1024)).toFixed(2);

    const remainingSize = totalSize.value - uploadedSize.value;
    const remainingTime = remainingSize / speed;
    const remainingMinutes = Math.floor(remainingTime / 60);
    const remainingSeconds = Math.floor(remainingTime % 60);
    const remainingTimeStr2 = `${remainingMinutes}:${remainingSeconds.toString().padStart(2, "0")}`;

    speedMBps.value = speedMBps2;
    remainingTimeStr.value = remainingTimeStr2;
  }

  if (completedChunks.value === totalChunks.value) {
    btnShow.value = false;
    // 更新统计信息
    stats.totalUploads++;
    stats.lastUploadTime = new Date().toLocaleString();
    saveStatsToStorage();
    // progressShow.value = false;
  }
};

// 获取全宗数据
const getFonds = () => {
  proxy.$vueAxios.get("MasterBaseFonds/GetFondsTree").then((res: any) => {
    FondsData.value = transTree(res.List, "Fonds_ID", "Fonds_Father");
    Fonds_ID.value = res.List[0].Fonds_ID;
    onChange(Fonds_ID.value);
  });
};

// 切换全宗
const onChange = (value: string) => {
  getCatalog(value).then((res: any) => {
    FMData.value = res;
    treeSetting.treeNode = {};
  });
};

// 切换门类
const onChangeFM = (value: string) => {
  const param = {
    order: "Catalog_Order asc",
    dtoList: [{ fieldName: "FM_ID", fieldValue: value, conditionalType: 0 }]
  };
  proxy.$vueAxios.post("Master_Base_Catalog/GetConditional", param).then((res: any) => {
    const result: any[] = [];
    res.List.filter((v: any) => v.Is_UnCatalog !== true && v.Catalog_Code !== "Recycle").forEach((item: any) => {
      result.push({ ...item, Catalog_Name: `${item.Catalog_Code} ${item.Catalog_Name}`, open: item.Catalog_Enable_Expand });
    });
    treeSetting.treeData = result;
  });
};

// 初始化树
const handleCreated = (obj: any) => {
  ztreeObj.value = obj;
};

// 树节点点击事件
const onClick = (treeNode: any) => {
  treeSetting.treeNode = treeNode;
  proxy.$vueAxios
    .post("Master_Base_AllInfos/GetConditional", {
      order: "AI_Index asc",
      dtoList: [{ fieldName: "Catalog_ID", fieldValue: treeNode.Catalog_ID }]
    })
    .then((res: any) => {
      console.log("测试一下", res.List);
    });
};

// 搜索事件
const onSearch = () => {
  if (searchVal.value) {
    const nodes = ztreeObj.value.getNodesByParamFuzzy("Catalog_Name", searchVal.value, null);
    treeSetting.treeData = nodes;
  } else {
    onChangeFM(FM_ID.value);
  }
};

onMounted(() => {
  getFonds();
  loadHistoryFromStorage();
  loadStatsFromStorage();
});
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>
